﻿#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
// 共享队列，用于存储生产者生成的数据
std::queue<int> q;
// 互斥量，用于保护队列和 finished 标志的线程安全访问
std::mutex mtx;
// 条件变量，用于实现线程间的等待和通知机制
std::condition_variable cv;
// 标志位，表示生产者是否已经完成生产
bool finished = false;
// 生产者线程函数
void producer() {
    for (int i = 0; i < 5; ++i) {
        {
            // 创建 unique_lock，锁定互斥量 mtx，保护共享队列
            std::unique_lock<std::mutex> lock(mtx);
            // 向队列中添加数据
            q.push(i);
            // 输出生产的数据
            std::cout << "Produced: " << i << std::endl;
        } // lock 离开作用域，自动解锁互斥量
        // 通知消费者，有新数据可消费
        cv.notify_one();
        // 模拟生产延迟
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    {
        // 再次加锁，准备修改 finished 标志
        std::unique_lock<std::mutex> lock(mtx);
        // 生产完成，设置标志
        finished = true;
    } // 作用域结束，解锁
    // 通知所有等待的消费者线程，生产已经结束
    cv.notify_all();
}
// 消费者线程函数
void consumer() {
    while (true) {
        // unique_lock 上锁，保护共享资源
        std::unique_lock<std::mutex> lock(mtx);
        // 等待条件变量，直到队列不为空或者生产结束
        cv.wait(lock, []{ return !q.empty() || finished; });
        // 如果队列有数据，则取出数据
        if (!q.empty()) {
            int val = q.front();
            q.pop();
            // 输出消费的数据
            std::cout << "Consumed: " << val << std::endl;
        }
            // 如果队列为空且生产者已经结束，退出循环
        else if (finished) {
            break;
        }
        // 若队列为空且生产未结束，则继续等待
    }
}

int main() {
    // 启动生产者线程
    std::thread t1(producer);
    // 启动消费者线程
    std::thread t2(consumer);
    // 等待生产者线程结束
    t1.join();
    // 等待消费者线程结束
    t2.join();
    return 0;
}